﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using WorkItemAnalyser.Core.Assertions;

namespace WorkItemAnalyser.Core.Parsers
{
    public class TextRuleParser : IRuleParser<string>
    {
        readonly IAssertionParser[] assertionParsers;

        public TextRuleParser()
            : this(new IAssertionParser[]
                       {new TextLinkAssertionParser(),
                       new TextFieldAssertionParser()})
        { }

        public TextRuleParser(IAssertionParser[] parsers)
        {
            assertionParsers = parsers;
        }

        private Rule ParseRule(string ruleText)
        {
            var parts = ruleText.Split(',');

            if (parts.Length != 2)
                return null;

            var query = ParseQuery(parts[0].Trim());
            if (query == null) return null;

            var assertion = ParseAssertion(parts[1].Trim());
            if (assertion == null) return null;

            return new Rule(query, assertion);
        }

        private IAssertion ParseAssertion(string assertionText)
        {
            return assertionParsers.Select(parser => parser.ParseAssertion(assertionText))
                                                    .FirstOrDefault(assertion => assertion != null);
        }

        private Query ParseQuery(string queryText)
        {
            var queryGrammer = @"each (?<workItemType>.*) in (?<project>.*)";
            var expression = new Regex(queryGrammer);

            var matches = expression.Match(queryText);

            if (!matches.Success) return null;

            return new Query(matches.Groups["workItemType"].ToString(), matches.Groups["project"].ToString());
        }

        private IEnumerable<string> GetLines(string ruleText)
        {
            return ruleText.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
        }

        public IEnumerable<Rule> RetrieveRules(string ruleInput)
        {
            return GetLines(ruleInput)
                .Select(line => ParseRule(line))
                .Where(rule => rule != null)
                .ToArray();
        }
    }
}

